package tech

import "ssp/set"

func (s *Solve) UniqueRectangleA(g *Grid) (used bool, results []*Result) {
	return urTemplate(g, g.doURTypeA)
}

func (g *Grid) doURTypeA(rect []*Cell) (used bool, results []*Result) {
	pCells := []*Cell{}
	for _, cell := range rect[1:] {
		if cell.cands != rect[0].cands {
			pCells = append(pCells, cell)
		}
	}
	if len(pCells) != 3 {
		return
	}

	for _, cell := range pCells {
		if cell.cands.Count() != 3 {
			return
		}
	}

	alsStrongs := g.initNWingStrongs()
	cands := rect[0].cands

	headCandStrongsss := make([][][]GroupItem, 3)
	for i, pcell := range pCells {
		cand := pcell.cands.Diff(cands).GetList()[0]
		weaks := g.findNNWeaks(cand, pcell)
		headCandStrongsss[i] = g.findNNStrongs(weaks, alsStrongs)
	}
	candHeadStrongsss := make([][][]GroupItem, 9)
	for cand := range 9 {
		candHeadStrongsss[cand] = make([][]GroupItem, len(headCandStrongsss))
	}
	for head, candStrongss := range headCandStrongsss {
		for cand, strongs := range candStrongss {
			candHeadStrongsss[cand][head] = strongs
		}
	}
	for cand, headStrongss := range candHeadStrongsss {
		if ok, rs := g.findTypeAZCells(rect, pCells, cand, headStrongss); ok {
			used = true
			results = append(results, rs...)
		}
	}

	return
}

func (g *Grid) findTypeAZCells(rect, pCells []*Cell, cand int, headStrongss [][]GroupItem) (used bool, results []*Result) {
	for _, zGroupItems := range mzip(headStrongss) {
		zCells := []*Cell{}
		for _, zGroupItem := range zGroupItems {
			for _, cell := range zGroupItem.getCells() {
				if cell == nil {
					break
				}
				if !cell.cands.Has(cand) {
					continue
				}
				zCells = append(zCells, cell)
			}
		}
		if len(zCells) < 2 {
			continue
		}
		ok, rmCells := g.canRemoveSeenCands(set.NewSet(cand), zCells)
		if !ok {
			continue
		}
		used = true
		if OUTPUTRESULT {
			result := new(Result)
			for _, zGroupItem := range zGroupItems {
				result.addHelpCells(zGroupItem.getCells())
			}
			g1 := result.getHelpCandsGroup()
			g1.add(rect[0].cands, rect)
			g2 := result.getHelpCandsGroup()
			for _, cell := range pCells {
				g2.add(cell.cands.Diff(rect[0].cands), []*Cell{cell})
			}
			result.addRemoved(set.NewSet(cand), rmCells)
			result.setStrategyName("UR+NWing")
			results = append(results, result)
		}
		if CHANGE {
			removeCands(set.NewSet(cand), rmCells)
		}
		if !EXHAUSTIVE {
			return
		}
	}

	return
}
